/**
 * @file CTimer.hpp Deklaracia triedy CTimer.
 *
 * @author Martin Kosorinský.
 * @date 15.3.2006.
 */

#ifndef CTIMER_HEADER
#define CTIMER_HEADER

#include <ctime>

/**
 * @brief Trieda reprezentujúca stopky na meranie času v programoch.
 * Trieda zapúzdruje obvyklé operácie potrebné pre meranie času vykonávania programového kódu.
 * Na meranie času využíva štandardné metódy jazyka C++. Využíva procedúru clock() na meranie
 * počtu cyklov procesora. Tie sú v závislosti od konštanty CLOCKS_PER_SEC konvertované na
 * čas v sekundách.
 * Trieda medzi inými operáciami umožňuje zastaviť meranie času, resp. pokračovanie v meraní.
 * Výstup merania je vo forme sekúnd v tvare desatinného čísla s dvojitou presnosťou.
 * @warning Trieda zabezpečuje meranie času procesora, nie reálneho času behu.
 */
class CTimer {
protected:
    /**
     * @brief Stav počtu cyklov v momente spustenia aktuálneho merania.
     */
    clock_t startTime;
    /**
    * @brief Pamäť pre počet cyklov ubehnutých pred prerušením merania.
    */
    clock_t pastTime;
    /**
     * @brief Flag signalizujúci aktuálny stav merania (beží,nebeží).
     */
    bool run;
public:
    /**
     * @brief Základný (implicitný) konštruktor, ktorý spustí meranie času.
     */
    CTimer() {
        start();
    };
    /**
     * @brief Funkcia vracia nameraný čas.
     * @param[in] del je celé číslo reprezentujúce počet opakovaní meranej operácie. Vydelením celkového času týmto
     * číslom získame jednotkový čas behu operácie, ktorý bude výstupom funkcie.
     * @warning Získaný čas nie je reálny čas behu meraného kódu, ale čas procesora počas behu.
     * @return Vráti desatinné číslo typu double, reprezentujúce počet sekúnd, ktoré ubehli počas merania
     * vrátane času ubehnutého počas predošlých meraní (ak neboli explicitne vynulované). Výstup je normovaný pre
     * jeden bez meranej operácie - celkový čas je vydelený počtom opakovaní @a del meranej operácie.
     */
    inline double getTime(const int del = 1) const {
        if (run)
            return (clock() - startTime + pastTime) / (double)(CLOCKS_PER_SEC * del);
        else
            return (pastTime) / (double)(CLOCKS_PER_SEC * del);
    };
    /**
     * @brief Procedúra spúšťajúca nové meranie.
     * Volaním procedúry je vynulovaná pamäť predošlých meraní a je spustené nové meranie.
     */
    inline void start() {
        pastTime = 0;
        run = true;
        startTime = clock();
    };
    /**
     * @brief Procedúra zastavujúca meranie.
     * Pri zastavení merania je uložený ubehnutý čas, tak aby bolo možné neskôr pokračovať v meraní.
     * @see unpause.
     */
    inline void pause() {
        pastTime += (clock() - startTime);
        run = false;
    };
    /**
     * @brief Procedúra spúšťajúca meranie.
     * Pri spustení sa pokračuje v predošlom meraní. Do celkového nameraného času sa tak pripočítajú
     * aj predošlé merania uložené v pamäti.
     * @see pause.
     */
    inline void unpause() {
        run = true;
        startTime = clock();
    };
};
#endif /*CTIMER_HEADER*/
